/*
    SUSAN® - Sole of Unix Save ANything

   Copyright (C) 2003-2010 Hechzh Property
      Copyright (C) 2011-2016 Skyatlas Co. LTD

   

   
*/
/*
 * Kern Sibbald May MMIII
 */
/**
 * @file
 * Bareos low level File I/O routines.  This routine simulates
 * open(), read(), write(), and close(), but using native routines.
 * I.e. on Windows, we use Windows APIs.
 */

#ifndef BAREOS_FINDLIB_BFILE_H_
#define BAREOS_FINDLIB_BFILE_H_

/* this should physically correspond to WIN32_STREAM_ID
 * from winbase.h on Win32. We didn't inlcude cStreamName
 * as we don't use it and don't need it for a correct struct size.
 */

#define WIN32_BACKUP_DATA 1

typedef struct _BWIN32_STREAM_ID {
  int32_t dwStreamId;
  int32_t dwStreamAttributes;
  int64_t Size;
  int32_t dwStreamNameSize;
} BWIN32_STREAM_ID, *LPBWIN32_STREAM_ID;


typedef struct _PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT {
  int64_t liNextHeader;
  bool bIsInData;
  BWIN32_STREAM_ID header_stream;
} PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT;

/*  =======================================================
 *
 *   W I N D O W S
 *
 *  =======================================================
 */
#if defined(HAVE_WIN32)

enum
{
  BF_CLOSED,
  BF_READ, /* BackupRead */
  BF_WRITE /* BackupWrite */
};

/* In bfile.c */

/* Basic Win32 low level I/O file packet */
/* clang-format off */
struct BareosWinFilePacket {
  bool use_backup_api = false;      /**< set if using BackupRead/Write */
  bool encrypted = false;           /**< set if using ReadEncryptedFileRaw/WriteEncryptedFileRaw */
  int mode = BF_CLOSED;             /**< set if file is open */
  HANDLE fh = INVALID_HANDLE_VALUE; /**< Win32 file handle */
  int fid = 0;                      /**< fd if doing Unix style */
  LPVOID lplugin_private_context = nullptr;       /**< BackupRead/Write context */
  PVOID pvContext = nullptr;        /**< Encryption context */
  POOLMEM* errmsg = nullptr;        /**< error message buffer */
  DWORD rw_bytes = 0;               /**< Bytes read or written */
  DWORD lerror = 0;                 /**< Last error code */
  int BErrNo = 0;                   /**< errno */
  boffset_t offset = 0;             /**< Delta offset */
  JobControlRecord* jcr = nullptr;  /**< jcr for editing job codes */
  PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32Decomplugin_private_context{0}; /**< context for decomposition
                                                                   of win32 backup streams */
  int use_backup_decomp = 0; /**< set if using BackupRead Stream Decomposition */
  bool reparse_point = false; /**< set if reparse point */
  bool cmd_plugin = false;    /**< set if we have a command plugin */
};
/* clang-format on */

HANDLE BgetHandle(BareosWinFilePacket* bfd);

#else /* Linux/Unix systems */

/*  =======================================================
 *
 *   U N I X
 *
 *  =======================================================
 */

/* Basic Unix low level I/O file packet */
/* clang-format off */
struct BareosWinFilePacket {
  int fid{0};                     /**< file id on Unix */
  int flags_{0};                  /**< open flags */
  int BErrNo{0};                  /**< errno */
  int32_t lerror{0};              /**< not used - simplies Win32 builds */
  boffset_t offset{0};            /**< Delta offset */
  JobControlRecord* jcr{nullptr}; /**< jcr for editing job codes */
  PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32Decomplugin_private_context{0}; /**< context for decomposition
                                                                   of win32 backup streams */
  int use_backup_decomp{0};       /**< set if using BackupRead Stream Decomposition */
  bool reparse_point{false};      /**< not used in Unix */
  bool cmd_plugin{false};         /**< set if we have a command plugin */
};
/* clang-format on */

#endif

void binit(BareosWinFilePacket* bfd);
bool IsBopen(BareosWinFilePacket* bfd);
bool set_win32_backup(BareosWinFilePacket* bfd);
bool SetPortableBackup(BareosWinFilePacket* bfd);
bool SetCmdPlugin(BareosWinFilePacket* bfd, JobControlRecord* jcr);
bool have_win32_api();
bool IsPortableBackup(BareosWinFilePacket* bfd);
bool IsRestoreStreamSupported(int stream);
bool is_win32_stream(int stream);
int bopen(BareosWinFilePacket* bfd,
          const char* fname,
          int flags,
          mode_t mode,
          dev_t rdev);
int BopenRsrc(BareosWinFilePacket* bfd,
              const char* fname,
              int flags,
              mode_t mode);
int bclose(BareosWinFilePacket* bfd);
ssize_t bread(BareosWinFilePacket* bfd, void* buf, size_t count);
ssize_t bwrite(BareosWinFilePacket* bfd, void* buf, size_t count);
boffset_t blseek(BareosWinFilePacket* bfd, boffset_t offset, int whence);
const char* stream_to_ascii(int stream);

bool processWin32BackupAPIBlock(BareosWinFilePacket* bfd,
                                void* pBuffer,
                                ssize_t dwSize);

#endif /* BAREOS_FINDLIB_BFILE_H_ */
